package com.yangguo.code.generator.util;

import java.net.InetAddress;
import java.net.NetworkInterface;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Map;
import java.util.TreeMap;
import java.util.stream.Collectors;

import javax.crypto.Cipher;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * 加密工具类
 * @author Noise
 */
@Slf4j
public class MyEncryptionUtil {

    private static String ivParameter = "abghtrkilpggdefg";
    /**
     * 西城加密工具类
     * @param appKey
     * @param appUuid
     * @param reqUuid
     * @param secret
     * @return
     * @throws Exception
     */
    public static String generateXCSignature(String appKey, String appUuid, String reqUuid, String secret,String messageId) throws Exception {
        String rawstr = "app_key=" + appKey + "&app_uuid=" + appUuid + "&req_uuid=" + reqUuid;
        log.info("[ 西城-加密 ] >>该条数据[ {} ]待加密内容：{}", messageId,rawstr);
        Mac sha1HMac = Mac.getInstance("HmacSHA1");
        SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
        sha1HMac.init(secretKey);
        byte[] array = sha1HMac.doFinal(rawstr.getBytes(StandardCharsets.UTF_8));
        if (array == null || array.length == 0) {
            return null;
        }
        // String result = new BASE64Encoder().encode(array)
        String result = Base64.encodeBase64String(array)
                .replace("=","")
                .replace("+","*")
                .replace("/","-");
        // log.info("西城-加密后签名：" + result);
        log.info("[ 西城-加密 ] >>该条数据[ {} ]加密后签名内容：{}",messageId, result);
        return result;
    }

    /**
     * 大兴加密工具类
     * @param appKey
     * @param appUuid
     * @param reqUuid
     * @param secret
     * @return
     * @throws Exception
     */
    public static String generateSignature(String appKey, String appUuid, String reqUuid, String secret) throws Exception {
        String rawstr = "app_key=" + appKey + "&app_uuid=" + appUuid + "&req_uuid=" + reqUuid;
        // log.info("大兴-待加密内容：" + rawstr);
        log.info("[ 大兴-加密 ] >>待加密内容：{}", rawstr);
        Mac sha1HMac = Mac.getInstance("HmacSHA1");
        SecretKeySpec secretKey = new SecretKeySpec(secret.getBytes(StandardCharsets.UTF_8), "HmacSHA1");
        sha1HMac.init(secretKey);
        byte[] array = sha1HMac.doFinal(rawstr.getBytes(StandardCharsets.UTF_8));
        if (array == null || array.length == 0) {
            return null;
        }
        // String result = new BASE64Encoder().encode(array);
        String result = Base64.encodeBase64String(array);
        // log.info("大兴-加密后签名：" + result);
        log.info("[ 大兴-加密 ] >>加密后签名内容：{}", result);
        return result;
    }



    /**
     * 通州加密-CBC模式
     *
     * @param sSrc 待加密字符串
     * @param sKey 私钥
     * @return 加密结果字符串
     * @throws Exception 异常
     */
    public static String encryptCbc(String sSrc, String sKey) throws Exception {
        // System.out.println("私钥："+sKey);
        log.info("[ 通州-加密 ] >>私钥：{}", sKey);
        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        byte[] raw = sKey.getBytes("ASCII");
        SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
        IvParameterSpec iv = new IvParameterSpec(ivParameter.getBytes());
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
        byte[] encrypted = cipher.doFinal(sSrc.getBytes(StandardCharsets.UTF_8));
        String result = Base64.encodeBase64String(encrypted);
        log.info("[ 通州-加密 ] >>加密后签名内容：{}", result);
        // return new BASE64Encoder().encode(encrypted);
        return result;
    }

    /**
     * 温榆河加密
     * @param data
     * @param key
     * @return
     * @throws Exception
     */
    public static String getEnc3DES(String data, String key) throws Exception {
        String iv= LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        // log.info("温榆河-加密前：" + data);
        log.info("[ 温榆河-加密 ] >>待加密内容：{}", data);
        Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding");
        DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("gb2312"));
        IvParameterSpec ivs = new IvParameterSpec(iv.getBytes("gb2312"));
        SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
        SecretKey securrekey = keyFactory.generateSecret(dks);
        cipher.init(Cipher.ENCRYPT_MODE, securrekey, ivs);
        // BASE64Encoder base64Encoder = new BASE64Encoder();
        // return base64Encoder.encode(cipher.doFinal(data.getBytes("gb2312")));
        String result = Base64.encodeBase64String(cipher.doFinal(data.getBytes("gb2312")));
        log.info("[ 温榆河-加密 ] >>加密后签名内容：{}", result);
        return result;
    }


    /**
     * 大兴报送发送参数加密
     * @param param
     * @param dataKey
     * @return
     */
    public static String paramSign(String param, String dataKey) {
        try {
            SecretKeySpec keySpec = new SecretKeySpec(dataKey.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, keySpec);

            byte[] encryptedData = cipher.doFinal(param.getBytes());

            String base64Encrypted = java.util.Base64.getEncoder().encodeToString(encryptedData);
            return base64Encrypted;
        } catch (Exception e) {
            log.error("[北京大兴]发送参数加密失败错误信息[{}]", e.getMessage());
        }
        return "";
    }

    /**
     * 西城报送发送参数加密
     * @param param
     * @param dataKey
     * @return
     */
    public static String xiChengParamSign(String param, String dataKey) {
        try {
            SecretKeySpec keySpec = new SecretKeySpec(dataKey.getBytes(), "AES");
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            cipher.init(Cipher.ENCRYPT_MODE, keySpec);

            byte[] encryptedData = cipher.doFinal(param.getBytes());

            String base64Encrypted = java.util.Base64.getEncoder().encodeToString(encryptedData);
            return base64Encrypted;
        } catch (Exception e) {
            log.error("[北京西城]发送参数加密失败错误信息[{}]", e.getMessage());
        }
        return "";
    }
    /**
     * 获取本机mac地址
     * @return
     */
    public static String getLocalMac() {
        try {
            InetAddress ia = InetAddress.getLocalHost();
            byte[] mac = NetworkInterface.getByInetAddress(ia).getHardwareAddress();
            StringBuffer sb = new StringBuffer("");
            for (int i = 0; i < mac.length; i++) {
                if (i != 0) {
                    sb.append("-");
                }
                int temp = mac[i] & 0xff;
                String str = Integer.toHexString(temp);
                if (str.length() == 1) {
                    sb.append("0" + str);
                } else {
                    sb.append(str);
                }
            }
            String localMAC = sb.toString().toUpperCase();
            return localMAC;
        } catch (Exception e) {
            log.error("获取本机mac地址失败", e);
        }
        return "";
    }

    /**
     * 大兴签名加密
     * @param appSecret
     * @param context
     * @return
     */
    public static String sign(String appSecret, String context) {
        try {
            Mac hmacSha1 = Mac.getInstance("HmacSHA1");
            SecretKeySpec secretKey = new SecretKeySpec(appSecret.getBytes(), "HmacSHA1");
            hmacSha1.init(secretKey);
            byte[] resultSha1 = hmacSha1.doFinal(context.getBytes());
            String base64Sha1 = java.util.Base64.getEncoder().encodeToString(resultSha1);
            return base64Sha1;
        } catch (Exception e) {
            log.error("[北京大兴]加密失败错误信息[{}]", e.getMessage());
        }
        return "";
    }

    /**
     * 西城签名加密
     * @param appSecret
     * @param context
     * @return
     */
    public static String xiChengSign(String appSecret, String context) {
        try {
            Mac hmacSha1 = Mac.getInstance("HmacSHA1");
            SecretKeySpec secretKey = new SecretKeySpec(appSecret.getBytes(), "HmacSHA1");
            hmacSha1.init(secretKey);
            byte[] resultSha1 = hmacSha1.doFinal(context.getBytes());
            String base64Sha1 = java.util.Base64.getEncoder().encodeToString(resultSha1);
            return base64Sha1;
        } catch (Exception e) {
            log.error("[北京西城]加密失败错误信息[{}]", e.getMessage());
        }
        return "";
    }


    public static String daxingEncryptV40(String key, String algorithm, String data) {
        try {
            Mac macAlgorithm = Mac.getInstance(algorithm);
            SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), algorithm);
            macAlgorithm.init(secretKey);
            byte[] body = macAlgorithm.doFinal(data.getBytes());
            // 转base64
            String base64 = java.util.Base64.getEncoder().encodeToString(body);
            // 将"+"替换为"*"，"/"替换为"-"，"="去除。
            base64 = StringUtils.replace(base64, "+", "*").replace("/", "-").replace("=", "");
            return base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static String getContent(Map<String, Object> map) {
        return map.entrySet().stream()
                .map(m -> m.getKey() + "=" + m.getValue())
                .collect(Collectors.joining("&"));
    }

    public static String replaceStr(String str) {
        return str.replace("+", "*").replace("/", "-").replace("=", "");
    }

    public static void main(String[] args) {
        TreeMap<String, Object> systemMap = new TreeMap<>();
        systemMap.put("app_key", "655a393e-6fc5-ad11-b4cf-6a753a93b538");
        systemMap.put("app_uuid", "90-E8-68-D6-37-DD");
        systemMap.put("req_uuid","563c67ae18f8415ca4705ba91aa17a25");
        systemMap.put("timestamp", 1701768442);
        systemMap.put("sig_method", "HMAC-SHA1");
        String systemContent = getContent(systemMap);
        String sign1 = MyEncryptionUtil.sign("655a393e-6fc5-ad11-ed5e-905c812645d2", systemContent);
        String systemReplace = replaceStr(sign1);
        System.out.println("签名1:"+systemReplace);
        Map<String, Object> map = new TreeMap<>();
        map.put("app_key", "655a393e-6fc5-ad11-b4cf-6a753a93b538");
        map.put("app_uuid", "90-E8-68-D6-37-DD");
        map.put("req_uuid","563c67ae18f8415ca4705ba91aa17a25");
        map.put("timestamp", 1701768442);
        map.put("sig_method", "HMAC-SHA1");
        StringBuilder sb = new StringBuilder();
        for(Map.Entry<String, Object> ent : map.entrySet()) {
            if (StringUtils.isNotBlank(sb)) {
                sb.append("&");
            }
            sb.append(ent.getKey() + "=" + ent.getValue());
        }
        String sign2 =
            MyEncryptionUtil.daxingEncryptV40("655a393e-6fc5-ad11-ed5e-905c812645d2", "HmacSHA1", sb.toString());

        System.out.println("签名2:"+sign2);
    }

}
